.Dd September 21, 2025
.Dt R_LANG 3
.Os
.Sh NAME
.Nm r_lang
.Nd Scripting language support library for radare2
.Sh SYNOPSIS
.Pp
Use this section to show the public header and the basic include needed to build
against the r_lang API; it gives the minimal compile-time view of the library.
.Pp
.In r_lang.h
.Pp
.Sh DESCRIPTION
.Pp
Readers will find here a concise overview of the goals and structure of the
r_lang module: a plugin-driven runtime that lets radare2 host and run scripts
and REPLs from multiple languages.
.Pp
The
.Nm r_lang
library provides scripting language support for radare2 through a plugin-based system.
It allows executing code in various programming languages within the radare2 environment,
enabling automation, custom commands, and extensions.
.Pp
At the heart of the API is
.Vt struct r_lang_t ,
which manages loaded language plugins, user pointers and execution sessions.
Language implementations register a
.Vt struct r_lang_plugin_t ,
supplying callbacks for initialization, running code, running files, interactive
prompts and cleanup.
.Sh INITIALIZATION
.Pp
This section documents how to create and destroy an r_lang handle and how to
associate runtime state (typically a pointer to an RCore instance) with it.
.Pp
Create a new language instance:
.Bd -literal -offset indent
RLang *lang = r_lang_new();
.Ed
.Pp
Set user pointer (usually RCore):
.Bd -literal -offset indent
r_lang_set_user_ptr(lang, core);
.Ed
.Pp
Free when done:
.Bd -literal -offset indent
r_lang_free(lang);
.Ed
.Sh EXECUTION
.Pp
Use these calls to select a language plugin, execute code buffers, or invoke
script files. The typical host (radare2) selects a plugin then calls one of the
run helpers shown below.
.Pp
Select a language:
.Bd -literal -offset indent
r_lang_use(lang, "qjs"); // QuickJS JavaScript
.Ed
.Pp
Execute code string:
.Bd -literal -offset indent
const char *code = "console.log('Hello from r2!');";
r_lang_run_string(lang, code);
.Ed
.Pp
Execute code with length:
.Bd -literal -offset indent
r_lang_run(lang, code, strlen(code));
.Ed
.Pp
Execute script file:
.Bd -literal -offset indent
r_lang_run_file(lang, "script.js");
.Ed
.Sh INTERACTIVE MODE
.Pp
Interactive features (REPLs) are implemented per-plugin and can be entered via
the generic prompt helper; this is the place to learn how to start a language
REPL from the embedding application.
.Pp
Start interactive prompt:
.Bd -literal -offset indent
r_lang_prompt(lang); // Interactive REPL
.Ed
.Sh ARGUMENTS
.Pp
Scripts that expect positional arguments receive them via the argv helpers; the
API lets hosts set argc/argv before invoking a file or an entry callback.
.Pp
Set command-line arguments for scripts:
.Bd -literal -offset indent
char *argv[] = {"script.js", "arg1", "arg2"};
r_lang_set_argv(lang, 3, argv);
.Ed
.Sh DEFINITIONS
.Pp
Use the definitions API to expose host pointers and typed variables to language
runtimes; the host can add and remove named definitions visible to scripts.
.Pp
Define variables accessible from scripts:
.Bd -literal -offset indent
int value = 42;
r_lang_define(lang, "int", "my_var", &value);
.Ed
.Pp
Remove definition:
.Bd -literal -offset indent
r_lang_undef(lang, "my_var");
.Ed
.Sh LANGUAGES
.Pp
This section highlights notable, supported language entry points rather than
exhaustively listing every plugin. It focuses on the two integration styles
commonly used by radare2: an embedded VM and native C plugin/script support.
.Pp
.Bl -bullet
.It
JavaScript: a native QuickJS (`qjs`) plugin is available and is the canonical
embedded scripting VM inside radare2. Use `r_lang_use(..., "qjs")` to select
it and `r_lang_run_string` / `r_lang_run_file` to execute code.
.It
C scripts: the C plugin compiles a `.c` file into a shared library, opens the
resulting library, resolves an `entry` symbol and calls it with the current
`RCore *` (stored in `r_lang->user`) and the configured `argc, argv`. The C
entry must have the signature `void entry(RCore *core, int argc, const char **argv)`.
.El
.Sh EXAMPLES
.Pp
The examples below show common usage patterns observed in the radare2 core:
invoking QuickJS code, running inline expressions via the `#!` hashbang helper,
and how C scripts are compiled and invoked with the host `RCore` pointer.
.Pp
Execute JavaScript code:
.Bd -literal -offset indent
#include <r_lang.h>

int main() {
    RLang *lang = r_lang_new();
    r_lang_use(lang, "qjs");
    
    const char *js_code = R"js(
        console.log("Hello from JavaScript!");
        var addr = 0x1000;
        console.log("Address: 0x" + addr.toString(16));
    )js";
    
    r_lang_run_string(lang, js_code);
    r_lang_free(lang);
    return 0;
}
.Ed
.Pp
Define and use variables:
.Bd -literal -offset indent
RLang *lang = r_lang_new();
int my_int = 12345;
r_lang_define(lang, "int", "global_var", &my_int);

r_lang_use(lang, "qjs");
r_lang_run_string(lang, "console.log('Value: ' + global_var);");

r_lang_free(lang);
.Ed
.Pp
Execute script file:
.Bd -literal -offset indent
r_lang_run_file(lang, "script.js");
.Ed
.Pp
Hashbang and `-e` usage (used by the `#!` command in `libr/core/cmd_hash.inc.c`):
.Bd -literal -offset indent
// the command handler implemented in libr/core/cmd_hash.inc.c parses `#!` lines
// and: selects the requested plugin (r_lang_get_by_name/r_lang_use_plugin),
// sets argv via r_lang_set_argv when file arguments are present, and either
// runs a file with r_lang_run_file or runs an expression with r_lang_run_string
// when `-e` is passed; expressions prefixed with `base64:` are decoded first.
.Ed
.Pp
C script example (how the C plugin runs code):
.Bd -literal -offset indent
/* example.c */
#include <r_core.h>

void entry(RCore *core, int argc, const char **argv) {
    char *s = r_core_cmd_str (core, "?E hello world");
    printf("%s", s);
    free (s);
}

/* The C plugin will compile this file to a shared library and call `entry` with
   the host RCore pointer (r_lang->user) and any argv configured via
   r_lang_set_argv(). */
.Ed
.Sh SEE ALSO
.Xr r_core 3 ,
.Xr r_util 3
